package com.uleth.mbank.aes;

/**
*
* @author Yunpu
*/

//import java.io.BufferedReader; 
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;

public class AESCipher {
	
    /** block Cipher Padding */
	private PaddedBufferedBlockCipher cipher = null;
    
	/** Cipher Key Length */
    private int keylength;
    
    final private boolean B_ENCRYPT=true;
    final private boolean B_DECRYPT=false;
    
    
    /**
     * setup Block Cipher's type, AES_Engine
     * @param block_cipher_engine
     */
    public void setEngine( BlockCipher block_cipher_engine){
 /*
  * Setup the AES cipher engine, create a PaddedBufferedBlockCipher
  * in CBC mode.
  */
        cipher = new PaddedBufferedBlockCipher(
                new CBCBlockCipher(block_cipher_engine));
    }
    
    /**
     * setup key length for Block Cipher
     * @param key_length
     */
    public void setKeyLength(int key_length){
        this.keylength= key_length;
    }
    
    /**
     * Initial Cipher Key
     * @param strKey
     */
    public void init(boolean encrypt,String strKey){
        /**
         * Initial Cipher Key
         */
        byte[] keybyte=new byte[this.keylength];
        keybyte=Hex.decode(strKey);
        /**
         * encrypt = B_ENCRYPT encrypt
         * encrypt = B_DECRYPT decrypt
         */
        cipher.init(encrypt, new KeyParameter(keybyte));
    }
    
    /**
     * Encrypt
     * @param input
     * @param Key
     * @return
     */
    public void Encrypt(InputStream inputstream,OutputStream outputstream) {
        /**
         * initial plain text
         */
        
        int inBlockSize = cipher.getBlockSize() * 10;
        int outBlockSize = cipher.getOutputSize(inBlockSize);
        
        byte[] inblock = new byte[inBlockSize];
        byte[] outblock = new byte[outBlockSize];
        
        int inL;	
        int outL;
        byte[] rv = null;
        try {
            while ((inL=inputstream.read(inblock, 0, inBlockSize)) > 0){
                outL = cipher.processBytes(inblock, 0, inL, outblock, 0);
    /*
     * Before we write anything out, we need to make sure
     * that we've got something to write out.
     */
                if (outL > 0){
                    rv = Hex.encode(outblock, 0, outL);
                    outputstream.write(rv, 0, rv.length);
                    outputstream.write('\n');
                }
            }
            
            try{
  /*
   * Now, process the bytes that are still buffered
   * within the cipher.
   */
                outL = cipher.doFinal(outblock, 0);
                if (outL > 0){
                    rv = Hex.encode(outblock, 0, outL);
                    outputstream.write(rv, 0, rv.length);
                    outputstream.write('\n');
                }
            } catch (CryptoException ce) {
                ce.printStackTrace();
            }
            
        } catch (DataLengthException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch(Exception e){
            e.printStackTrace();
        }
        
    }
    
	

	
	/** Creates a new instance of AESCipher */
    public AESCipher() {
    }
    
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
